package com.tanhua.server.service;

import com.alibaba.dubbo.config.annotation.Reference;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.tanhua.common.pojo.User;
import com.tanhua.common.pojo.UserInfo;
import com.tanhua.dubbo.api.QuanZiApi;
import com.tanhua.dubbo.api.VisitorsApi;
import com.tanhua.dubbo.pojo.Publish;
import com.tanhua.dubbo.pojo.Visitors;
import com.tanhua.dubbo.vo.PageInfo;
import com.tanhua.server.utils.RelativeDateFormat;
import com.tanhua.server.utils.UserThreadLocal;
import com.tanhua.server.vo.MovementVo;
import com.tanhua.server.vo.PageResult;
import com.tanhua.server.vo.PicUploadResult;
import com.tanhua.server.vo.VisitorsVo;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;

/**
 * 圈子模块
 */
@Service
public class MovementsService {

    @Autowired
    private UserService userService;

    @Autowired
    private PicUploadService picUploadService;

    @Autowired
    private UserInfoService userInfoService;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Reference(version = "1.0.0")
    private QuanZiApi quanZiApi;

    @Reference(version = "1.0.0")
    private VisitorsApi visitorsApi;

    /**
     * 发布动态
     *
     * @param textContent
     * @param location
     * @param latitude
     * @param longitude
     * @param multipartFile
     * @return
     */
    public String savePublish(String textContent, String location, String latitude, String longitude, MultipartFile[] multipartFile) {
        //查询当前的登录信息
        User user = UserThreadLocal.get();

        // 构建并填充publish对象
        Publish publish = new Publish();
        publish.setId(ObjectId.get());
        publish.setText(textContent);
        publish.setUserId(user.getId());
        publish.setCreated(System.currentTimeMillis());
        publish.setLatitude(latitude);
        publish.setLongitude(longitude);
        publish.setLocationName(location);
        // 上传图片
        List<String> picPath = new ArrayList<>();
        for (MultipartFile file : multipartFile) {
            PicUploadResult uploadResult = picUploadService.upload(file);
            picPath.add(uploadResult.getName());
        }
        publish.setMedias(picPath);

        return quanZiApi.savePublish(publish);
    }

    /**
     * 查看好友动态
     *
     * @param page
     * @param pagesize
     * @return
     */
    public PageResult queryUserPublishList(Integer page, Integer pagesize) {
        return queryPublishList(UserThreadLocal.get(), page, pagesize);
    }

    /**
     * 查看推荐动态
     *
     * @param page
     * @param pagesize
     * @return
     */
    public PageResult queryRecommendPublishList(Integer page, Integer pagesize) {
        page = 2;  // TODO
        return queryPublishList(null, page, pagesize);
    }

    /**
     * 点赞
     *
     * @param publishId 发布动态的id
     * @return 点赞数
     */
    public Long saveLikeComment(String publishId) {
        return saveAndGet(publishId, "LIKE", 1);
    }


    /**
     * 取消点赞
     *
     * @param publishId 发布动态的id
     * @return 点赞数
     */
    public Long removeLikeComment(String publishId) {
        return removeAndGet(publishId, "LIKE", 1);
    }

    // 喜欢
    public Long saveLoveComment(String publishId) {
        return saveAndGet(publishId, "LOVE", 3);
    }

    // 取消喜欢
    public Long removeLoveComment(String publishId) {
        return removeAndGet(publishId, "LOVE", 3);
    }
    /**
     * 查看单条动态
     *
     * @param publishId
     * @return
     */
    public MovementVo queryMovementsById(String publishId) {
        Publish publish = this.quanZiApi.queryPublishById(publishId);
        if (null == publish) {
            return null;
        }
        // 填充数据
        MovementVo movementVo = new MovementVo();
        movementVo.setId(publish.getId().toHexString());
        movementVo.setTextContent(publish.getText());
        movementVo.setImageContent(publish.getMedias().toArray(new String[]{}));
        movementVo.setCreateDate(RelativeDateFormat.format(new Date(publish.getCreated())));
        movementVo.setUserId(publish.getUserId());
        UserInfo userInfo = userInfoService.queryById(publish.getUserId());

        if (userInfo == null) {
            return null;
        }
        fillMovementsInfo(movementVo, userInfo);
        return movementVo;
    }

    /**
     * 谁看我
     *
     * @return
     */
    public List<VisitorsVo> queryVisitorsList() {
        User user = UserThreadLocal.get();

        // 如果redis中存在上次查询的时间，就按照这个时间之后查询，如果没有就查询前5个
        String redisKey = "visitor_date_" + user.getId();
        String date = this.redisTemplate.opsForValue().get(redisKey);
        List<Visitors> visitorsList = null;
        if (StringUtils.isNotEmpty(date)) {
            visitorsList = this.visitorsApi.topVisitor(user.getId(), Long.valueOf(date));
        } else {
            visitorsList = this.visitorsApi.topVisitor(user.getId(), 6);
        }

        // 如果查出来的集合为空，则返回一个空集合
        if (CollectionUtils.isEmpty(visitorsList)){
            return Collections.emptyList();
        }

        List<Long> ids = new ArrayList<>();
        for (Visitors visitors : visitorsList) {
            ids.add(visitors.getVisitorUserId());
        }

        // 查找访问用户的信息
        QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("user_id",ids);
        List<UserInfo> userInfoList = this.userInfoService.queryList(queryWrapper);

        // 遍历集合，封装访问用户的对象
        List<VisitorsVo> visitorsVoList = new ArrayList<>();
        for (Visitors visitors : visitorsList) {
            for (UserInfo userInfo : userInfoList) {
                if (visitors.getVisitorUserId().longValue() == userInfo.getUserId().longValue()){
                    VisitorsVo visitorsVo = new VisitorsVo();
                    visitorsVo.setId(userInfo.getUserId());
                    visitorsVo.setAvatar(userInfo.getLogo());
                    visitorsVo.setAge(userInfo.getAge());
                    visitorsVo.setGender(userInfo.getSex().name().toLowerCase());
                    visitorsVo.setNickname(userInfo.getNickName());
                    visitorsVo.setTags(StringUtils.split(userInfo.getTags(),','));
                    visitorsVo.setFateValue(visitors.getScore().intValue());
                    visitorsVoList.add(visitorsVo);
                    break;
                }
            }
        }
        return visitorsVoList;
    }

    /**
     * 查看个人相册动态
     *
     * @param page
     * @param pageSize
     * @param userId
     * @return
     */
    public PageResult queryMovementsList(Integer page, Integer pageSize, Long userId) {
        PageResult pageResult = new PageResult();
        pageResult.setPage(page);
        pageResult.setPagesize(pageSize);

        PageInfo<Publish> pageInfo = this.quanZiApi.queryAlbumList(userId, page, pageSize);
        List<Publish> records = pageInfo.getRecords();

        if(CollectionUtils.isEmpty(records)){
            return pageResult;
        }
        List<MovementVo> movementsList = new ArrayList<>();
        for (Publish record : records) {
            MovementVo movements = new MovementVo();

            movements.setId(record.getId().toHexString());
            movements.setImageContent(record.getMedias().toArray(new String[]{}));
            movements.setTextContent(record.getText());
            movements.setUserId(record.getUserId());
            movements.setCreateDate(RelativeDateFormat.format(new Date(record.getCreated())));

            movementsList.add(movements);
        }

        List<Long> userIds = new ArrayList<>();
        for (MovementVo movements : movementsList) {
            if (!userIds.contains(movements.getUserId())) {
                userIds.add(movements.getUserId());
            }
        }

        QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("user_id", userIds);
        List<UserInfo> userInfos = this.userInfoService.queryList(queryWrapper);
        for (MovementVo movementVo : movementsList) {
            for (UserInfo userInfo : userInfos) {
                if (movementVo.getUserId().longValue() == userInfo.getUserId().longValue()){
                    this.fillMovementsInfo(movementVo,userInfo);
                    break;
                }
            }
        }
        pageResult.setItems(movementsList);
        return pageResult;
    }


    /* ===================================================================
                                    公共方法
    =================================================================== */
    /**
     * 填充movements
     *
     * @param movementVo
     * @param userInfo
     */
    private void fillMovementsInfo(MovementVo movementVo, UserInfo userInfo) {
        User user = UserThreadLocal.get();
        movementVo.setAge(userInfo.getAge());
        movementVo.setAvatar(userInfo.getLogo());
        movementVo.setGender(userInfo.getSex().name().toLowerCase());
        movementVo.setNickname(userInfo.getNickName());
        movementVo.setTags(StringUtils.split(userInfo.getTags(), ","));
        movementVo.setCommentCount(10); //TODO 评论数
        movementVo.setDistance("1.2公里"); //TODO 距离

        // 点赞
        String likeKey = "QUANZI_COMMENT_LIKE_USER_" + user.getId() + "_" + movementVo.getId();
        movementVo.setHasLiked(redisTemplate.hasKey(likeKey) ? 1 : 0); //是否点赞
        String key = "QUANZI_COMMENT_LIKE_" + movementVo.getId();
        String likeValue = redisTemplate.opsForValue().get(key);
        if (org.apache.commons.lang3.StringUtils.isNotEmpty(likeValue)) {
            movementVo.setLikeCount(Integer.valueOf(likeValue)); //点赞数
        } else {
            movementVo.setLikeCount(0); //点赞数
        }

        // 喜欢
        String loveKey = "QUANZI_COMMENT_LOVE_USER_" + user.getId() + "_" + movementVo.getId();
        movementVo.setHasLoved(redisTemplate.hasKey(loveKey) ? 1 : 0); //是否喜欢
        String loveCountKey = "QUANZI_COMMENT_LOVE_" + movementVo.getId();
        String loveValue = redisTemplate.opsForValue().get(loveCountKey);
        if (org.apache.commons.lang3.StringUtils.isNotEmpty(loveValue)) {
            movementVo.setLoveCount(Integer.valueOf(loveValue)); //喜欢数
        } else {
            movementVo.setLoveCount(0); //喜欢数
        }
    }

    /**
     * 查看圈子动态
     *
     * @param user
     * @param page
     * @param pagesize
     * @return
     */
    private PageResult queryPublishList(User user, Integer page, Integer pagesize) {
        PageResult pageResult = new PageResult();
        Long userId = null; //默认查询推荐
        PageInfo<Publish> pageInfo = null;
        if (user == null) {
            String redisValue = this.redisTemplate.opsForValue().get("QUANZI_PUBLISH_RECOMMEND_" + UserThreadLocal.get().getId());
            if (StringUtils.isNotEmpty(redisValue)) {
                // 对命中的数据进行分割，得到pid的集合
                String[] pids = redisValue.split(",");
                // 开始索引计算公式：（当前页-1）*每页显示的大小
                int startIndex = (page - 1) * pagesize;
                if (startIndex < pids.length) {
                    int endIndex = startIndex + pagesize - 1;
                    if (endIndex >= pids.length - 1) {
                        endIndex = pids.length - 1;
                    }
                    List<Long> pidList = new ArrayList<>();
                    for (int i = startIndex; i <= endIndex; i++) {
                        pidList.add(Long.valueOf(pids[i]));
                    }
                    List<Publish> publishList = quanZiApi.queryPublishListByPids(pidList);
                    pageInfo = new PageInfo<>();
                    pageInfo.setRecords(publishList);
                }

            }
        }
        if (user != null) {
            userId = user.getId();
            pageInfo = quanZiApi.queryPublishList(userId, page, pagesize);
        }
        user = UserThreadLocal.get();
        pageResult.setCounts(0);
        pageResult.setPagesize(0);
        pageResult.setPage(page);
        pageResult.setPagesize(pagesize);

        // 如果pageInfo为空，直接返回
        if (pageInfo == null) {
            return pageResult;
        }
        // 获取发布信息的列表
        List<Publish> publishList = pageInfo.getRecords();
        if (null == publishList) {
            return pageResult;
        }
        // 封装movements列表对象
        List<MovementVo> movementVoList = new ArrayList<>();
        for (Publish publish : publishList) {
            MovementVo movementVo = new MovementVo();

            movementVo.setId(publish.getId().toHexString());
            movementVo.setImageContent(publish.getMedias().toArray(new String[]{}));
            movementVo.setTextContent(publish.getText());
            movementVo.setUserId(publish.getUserId());
            movementVo.setCreateDate(RelativeDateFormat.format(new Date(publish.getCreated())));

            movementVoList.add(movementVo);
        }

        List<Long> userIds = new ArrayList<>();
        for (MovementVo movementVo : movementVoList) {
            if (!userIds.contains(movementVo.getId())) {
                userIds.add(movementVo.getUserId());
            }

        }
        if (userIds.size() == 0) {
            return pageResult;
        }

        // 查询用户的信息并封装到movements中
        QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("user_id", userIds);
        List<UserInfo> userInfos = userInfoService.queryList(queryWrapper);
        for (MovementVo movementVo : movementVoList) {
            for (UserInfo userInfo : userInfos) {
                if (movementVo.getUserId().longValue() == userInfo.getUserId().longValue()) {
                    fillMovementsInfo(movementVo, userInfo);
                    break;
                }
            }
        }

        pageResult.setItems(movementVoList);
        return pageResult;
    }

    /**
     * 点赞和喜欢的公共方法
     *
     * @param publishId
     * @param what
     * @param type
     * @return
     */
    private Long saveAndGet(String publishId, String what, Integer type) {
        User user = UserThreadLocal.get();
        boolean result;
        if (StringUtils.equalsAnyIgnoreCase("LIKE", what)) {
            result = quanZiApi.saveLikeComment(user.getId(), publishId);
        } else {
            result = quanZiApi.saveLoveComment(user.getId(), publishId);
        }

        if (!result) {
            return null;
        }
        //保存点赞数到redis
        Long count;
        String key = "QUANZI_COMMENT_" + what + "_" + publishId;
        if (!redisTemplate.hasKey(key)) {
            count = quanZiApi.queryCommentCount(publishId, type);
            redisTemplate.opsForValue().set(key, String.valueOf(count));

        } else {
            count = redisTemplate.opsForValue().increment(key);
        }

        // 记录点赞
        String userKey = "QUANZI_COMMENT_" + what + "_USER_" + user.getId() + "_" + publishId;
        this.redisTemplate.opsForValue().set(userKey, "1");

        return count;
    }

    /**
     * 取消点赞和喜欢的公共方法
     *
     * @param publishId
     * @param what
     * @param type
     * @return
     */
    private Long removeAndGet(String publishId, String what, Integer type) {
        User user = UserThreadLocal.get();
        boolean result = quanZiApi.removeComment(user.getId(), publishId, type);
        if (!result) {
            return null;
        }
        // 点赞数减一
        String key = "QUANZI_COMMENT_" + what + "_" + publishId;
        Long count = redisTemplate.opsForValue().decrement(key);
        //删除已点赞标记
        String userKey = "QUANZI_COMMENT_" + what + "_USER_" + user.getId() + "_" + publishId;
        this.redisTemplate.delete(userKey);

        return count;
    }
}
